# -*- coding: utf-8 -*-
from lettuce import step
from lettuce import world

# ------------------------------------------------------------------------------
# TODO: move this class under test to another file
class GameClock(object):

    def __init__(self, get_ticks):
        self.get_ticks = get_ticks
        
    def tick(self):
        pass
 
# this is the looping method, the code from self.tick could probably
# be copied into this while loop, but then it can't be tested       
#    def run(self):
#        while 1: # TODO: use 'running' variable??    
#            self.tick()
    

# ------------------------------------------------------------------------------
# test helper methods

def update():
    world.real_time += world.update_elapsed
    world.capture.append('update')
    
def draw():
    world.real_time += world.draw_elapsed
    world.capture.append('draw')    

def get_ticks():
    return real_time

# ------------------------------------------------------------------------------


@step(u'Given a gameclock')
def given_a_gameclock(step):
    # TODO: how to test different implementations?? manually
    world.gameclock = GameClock(get_ticks)
    world.real_time = 0.0
    world.capture = []
    # this values might be manipulated within a step to simulate slow and fast hardware
    world.update_elapsed = 10
    world.draw_elapsed = 20
    world.update_interval = 5 # expected repeat time
    world.draw_interval = 1 # expected repeat time,  as fast as possible?

# @step(u'Then the update timer will be scheduled for callback each time its UPS interval has passed')
# def then_the_update_timer_will_be_scheduled_for_callback_each_time_its_ups_interval_has_passed(step):
    # assert len(world.captured) == 0, 'no update nor draw should have been called'
    # world.gameclock.tick()
    # world.real_time += world.update_interval / 2
    # world.gameclock.tick()
    # assert len(world.captured) == 0, 'no update nor draw should have been called if time does not progress enough'
    # world.real_time += world.update_interval
    # world.gameclock.tick()
    # assert len(world.captured) == 1, 'one update should have happend so far'

@step(u'Then the update timer will be scheduled for callback')
def then_the_update_timer_will_be_scheduled_for_callback(step):
    assert len(world.captured) == 0, 'no update nor draw should have been called'
    world.gameclock.tick()
    world.real_time += world.update_interval / 2
    world.gameclock.tick()
    assert len(world.captured) == 0, 'no update nor draw should have been called if time does not progress enough'
    world.real_time += world.update_interval
    world.gameclock.tick()
    assert len(world.captured) == 1, 'one update should have happend so far'

@step(u'When an update callback is registered')
def when_an_update_callback_is_registered(step):
    world.gameclock.register_update(upate, world.update_interval)

# @step(u'When a draw callback is registered')
# def when_a_draw_callback_is_registered(step):
    # assert False, 'This step must be implemented'

# @step(u'Then the draw timer will be scheduled for callback each time its FPS interval has passed')
# def then_the_draw_timer_will_be_scheduled_for_callback_each_time_its_fps_interval_has_passed(step):
    # assert False, 'This step must be implemented'

# @step(u'Then the draw callback will be called every chance it gets')
# def then_the_draw_callback_will_be_called_every_chance_it_gets(step):
    # assert False, 'This step must be implemented'

# @step(u'When the update time has come')
# def when_the_time_has_come(step):
    # assert False, 'This step must be implemented'

# @step(u'Then the update callback is called')
# def then_the_update_callback_is_called(step):
    # assert False, 'This step must be implemented'

# @step(u'Then the draw callback is called')
# def then_the_draw_callback_is_called(step):
    # assert False, 'This step must be implemented'

# @step(u'Given a gameclock and fast hardware')
# def given_a_gameclock_and_fast_hardware(step):
    # assert False, 'This step must be implemented'

# @step(u'When FPS is not throttled and its not calling update')
# def when_fps_is_not_throttled_and_its_not_calling_update(step):
    # assert False, 'This step must be implemented'

# @step(u'Then its calling draw_frame repeatedly until next update time has arrived')
# def then_its_calling_draw_frame_repeatedly_until_next_update_time_has_arrived(step):
    # assert False, 'This step must be implemented'

# @step(u'When a update interval has passed')
# def when_a_update_interval_has_passed(step):
    # assert False, 'This step must be implemented'

# @step(u'Given a gameclock and fast enough hardware')
# def given_a_gameclock_and_fast_enough_hardware(step):
    # assert False, 'This step must be implemented'

# @step(u'When updates and/or frames run longer than their intervals')
# def when_updates_and_or_frames_run_longer_than_their_intervals(step):
    # assert False, 'This step must be implemented'

# @step(u'Then the actual time of the gameclock does not drift compared to the real time')
# def then_the_actual_time_of_the_gameclock_does_not_drift_compared_to_the_real_time(step):
    # assert False, 'This step must be implemented'

# @step(u'Given a gameclock and slow hardware')
# def given_a_gameclock_and_slow_hardware(step):
    # assert False, 'This step must be implemented'

# @step(u'Then it should call update as fast as possible')
# def then_it_should_call_update_as_fast_as_possible(step):
    # assert False, 'This step must be implemented'

# @step(u'And call frame at least one time per max=N updates')
# def and_call_frame_at_least_one_time_per_max_n_updates(step):
    # assert False, 'This step must be implemented'

# @step(u'And the actual time of the gameclock does not drift compared to the real time')
# def and_the_actual_time_of_the_gameclock_does_not_drift_compared_to_the_real_time(step):
    # assert False, 'This step must be implemented'

# @step(u'When the the update call takes longer than the draw call')
# def when_the_the_update_call_takes_longer_than_the_draw_call(step):
    # assert False, 'This step must be implemented'

# @step(u'Then the gameclock should still work as normal')
# def then_the_gameclock_should_still_work_as_normal(step):
    # assert False, 'This step must be implemented'

# @step(u'When the update call takes less time than the draw call')
# def when_the_update_call_takes_less_time_than_the_draw_call(step):
    # assert False, 'This step must be implemented'

# @step(u'When the gameclock runs and the updates and draw calls take longer than their intervals')
# def when_the_gameclock_runs_and_the_updates_and_draw_calls_take_longer_than_their_intervals(step):
    # assert False, 'This step must be implemented'

# @step(u'Then it should slow down')
# def then_it_should_slow_down(step):
    # assert False, 'This step must be implemented'
    
# @step(u'When the draw time has come')
# def when_the_draw_time_has_come(step):
    # assert False, 'This step must be implemented'

# @step(u'When the duration of update is less than draw')
# def when_the_duration_of_update_is_less_than_draw(step):
    # assert False, 'This step must be implemented'

# @step(u'When the duration of update plus draw exceeds their intervals')
# def when_the_duration_of_update_plus_draw_exceeds_their_intervals(step):
    # assert False, 'This step must be implemented'

# @step(u'Then the draw timer will be scheduled for callback')
# def then_the_draw_timer_will_be_scheduled_for_callback(step):
    # assert False, 'This step must be implemented'
